﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Globalization;

namespace Server
{
    class iTrackProtocol
    {
        public enum MessageImei
        {
            Imei = 5
        }

        public enum MessageDateTime
        {
            Year = 9,
            Month = 10,
            Day = 11,
            Hour = 12,
            Minute = 13,
            Second = 14
        };

        public enum MessageCoordinate
        {
            Latitude = 15,
            Longitude = 19
        };

        public enum MessageSpeed
        {
            Speed = 23
        }

        public enum MessageHeading
        {
            Heading = 25
        }

        public enum MessageMileage
        {
            Mileage = 31
        }




        public static int GetImei(byte[] MessageDevice)
        {
            return BitConverter.ToInt32(MessageDevice, (int)MessageImei.Imei);                                
        }

        public static DateTime GetDateTime(byte[] MessageDevice)
        {            
            int Year = ConvertBCDToInt(MessageDevice[(int)MessageDateTime.Year]);
            int Month = ConvertBCDToInt(MessageDevice[(int)MessageDateTime.Month]);
            int Day = ConvertBCDToInt(MessageDevice[(int)MessageDateTime.Day]);

            int Hour = ConvertBCDToInt(MessageDevice[(int)MessageDateTime.Hour]);
            int Minute = ConvertBCDToInt(MessageDevice[(int)MessageDateTime.Minute]);
            int Second = ConvertBCDToInt(MessageDevice[(int)MessageDateTime.Second]);

            return new DateTime(Year, Month, Day, Hour, Minute, Second);
        }

        public static double GetCoordinate(byte[] MessageDevice, MessageCoordinate enumMessageCoordinate)
        {
            int index = (int)MessageCoordinate.Longitude;
            if (enumMessageCoordinate == MessageCoordinate.Latitude)
                index = (int)MessageCoordinate.Latitude;


            bool IsSouthHemisphere = (MessageDevice[index] & 128) != 0;

            string Hemisphere = "N";
            if (IsSouthHemisphere)
                Hemisphere = "S";

            string LatitudeFormat = string.Format("{0:X2}", MessageDevice[index] & 127) +
                                    string.Format("{0:X2}", MessageDevice[index + 1]);

            int Latitude = ConvertBCDToInt(MessageDevice[index + 2]);
            LatitudeFormat += Convert.ToString(Latitude / 10) + "." + Convert.ToString(Latitude % 10) + string.Format("{0:X2}", MessageDevice[index + 3]);


            double LatitudeNumber = double.Parse(LatitudeFormat, NumberStyles.Float, NumberFormatInfo.InvariantInfo);

            int LatitudeValue2 = (int)LatitudeNumber;
            int LatitudeValue3 = LatitudeValue2 % 100;
            int LatitudeValue4 = (LatitudeValue2 - LatitudeValue3) / 100;
            LatitudeNumber = (double)LatitudeValue4 + ((double)LatitudeValue3 + LatitudeNumber - (double)LatitudeValue2) / 60;

            if (Hemisphere == "W" || Hemisphere == "S")
                LatitudeNumber = -LatitudeNumber;

            return LatitudeNumber;

        }

        public static double GetSpeed(byte[] MessageDevice)
        {
            return Convert.ToDouble(ConvertBCDToInt(MessageDevice[(int)MessageSpeed.Speed]) * 100 + ConvertBCDToInt(MessageDevice[(int)MessageSpeed.Speed + 1]));
        }

        public static double GetHeading(byte[] MessageDevice)
        {
            return Convert.ToDouble(ConvertBCDToInt(MessageDevice[(int)MessageHeading.Heading]) * 100 + ConvertBCDToInt(MessageDevice[(int)MessageHeading.Heading + 1]));
        }

        //public static void Get()
        //{

        //    if (param1 & 128)
        //    {
        //        this.m_isUrgentAlarmSendSMS = true;
        //    }
        //    else
        //    {
        //        this.m_isUrgentAlarmSendSMS = false;
        //    }
        //    if (param1 & 64)
        //    {
        //        this.m_isOverspeedSendSMS = true;
        //    }
        //    else
        //    {
        //        this.m_isOverspeedSendSMS = false;
        //    }
        //    if (param1 & 32)
        //    {
        //        this.m_isEngineOnSendSMS = true;
        //    }
        //    else
        //    {
        //        this.m_isEngineOnSendSMS = false;
        //    }
        //    if (param1 & 16)
        //    {
        //        this.m_isShockSendSMS = true;
        //    }
        //    else
        //    {
        //        this.m_isShockSendSMS = false;
        //    }
        //    if (param1 & 8)
        //    {
        //        this.m_isDoorOpenSendSMS = true;
        //    }
        //    else
        //    {
        //        this.m_isDoorOpenSendSMS = false;
        //    }
        //    if (param1 & 4)
        //    {
        //        this.m_isMainPowerOffSendSMS = true;
        //    }
        //    else
        //    {
        //        this.m_isMainPowerOffSendSMS = false;
        //    }
        //    if (param1 & 2)
        //    {
        //        this.m_isFenceAlarmlSendSMS = true;
        //    }
        //    else
        //    {
        //        this.m_isFenceAlarmlSendSMS = false;
        //    }

        //}



        
        public static int ConvertBCDToInt(byte Data)
        {
            int returnData = (Data & 15) + (Data >> 4 & 15) * 10;
            return returnData;            
        }

        public static byte CalcCheckCode(byte[] MessageDevice)
        {
            byte num = 0;
            int num1 = 2;
            while (true)
            {
                bool length = num1 < (int)MessageDevice.Length - 2;
                if (!length)
                {
                    break;
                }
                num = (byte)(num ^ MessageDevice[num1]);
                num1++;
            }
            byte num2 = num;
            return num2;
        }



        


        public static string GetProtocol (byte[] arrData)
        {
            try
            {
                StringBuilder str = new StringBuilder();                
                
                str.AppendLine("Time");                
                DateTime dateTime = ParseDateTime(arrData, 9);
                str.AppendLine(dateTime.ToLongDateString());
                //str.AppendLine("Head:"+GpsGate.iTrac.iTracParser.ParseBCD(arrData[0]));
                double num =   ParseCoordinate(arrData, 15);
                double num1 = ParseCoordinate(arrData, 19);                
                double num2 = (double)(ParseBCD(arrData[23]) * 100 + ParseBCD(arrData[24]));
                double num3 = (double)(ParseBCD(arrData[25]) * 100 + ParseBCD(arrData[26]));
                bool flag = (arrData[27] & 128) != 0;
                str.AppendLine("TrackPoint");
                str.AppendLine("num: "+num.ToString());
                str.AppendLine("num1: " + num1.ToString());
                str.AppendLine("num2: " + num2.ToString());
                str.AppendLine("num3: " + num3.ToString());

                

                ////base.SetTrackPoint(new TrackPoint(new Position(num1, num), new Velocity(num2, num3, SpeedUnits.Kph), dateTime, flag));
                str.AppendLine("MainPowerCut:" + Convert.ToString((arrData[27] & 20) == 16));
                int num4 = arrData[31];
                int num5 = arrData[32];
                str.AppendLine(("ACC:" + Convert.ToString((num4 & 128) != 0)));
                str.AppendLine(("Input1:" + Convert.ToString((num4 & 64) != 0)));
                str.AppendLine(("Input2:" + Convert.ToString((num4 & 32) != 0)));
                str.AppendLine(("OilCuttingAlarm:" + Convert.ToString((num4 & 4) != 0)));
                str.AppendLine(("InflameAlarm:" + Convert.ToString((num4 & 2) != 0)));
                str.AppendLine(("POIAlarm:" + Convert.ToString((num4 & 1) != 0)));
                str.AppendLine(("Overspeed:" + Convert.ToString((num5 & 64) != 0)));
                str.AppendLine(("CarParkAlarm:" + Convert.ToString((num5 & 32) != 0)));
                str.AppendLine(("GeofenceExit:" + Convert.ToString((num5 & 16) != 0)));
                str.AppendLine(("GeofenceEnter:" + Convert.ToString((num5 & 8) != 0)));
                str.AppendLine(("OutOfRoadLine:" + Convert.ToString((num5 & 4) != 0)));
                str.AppendLine(("DisplacementAlarm:" + Convert.ToString((num5 & 2) != 0)));
                str.AppendLine(("OvertimeDriving:" + Convert.ToString((num5 & 1) != 0)));

                

                return str.ToString();
            
            }
            catch (Exception exception1)
            {
                Exception exception = exception1;
               // throw new FormatException(string.Format("Could not parse {0}", iTracParser.LogBinary(null, arrData)), exception);

                return "";
            }

            
        }

        public static string GetProtocol2(byte[] arrData)
        {
            try
            {
                StringBuilder str = new StringBuilder();

                //str.AppendLine("Time");
                //DateTime dateTime = ParseDateTime(arrData, 9);
                //str.AppendLine(dateTime.ToLongDateString());
                //str.AppendLine("Head:" + GpsGate.iTrac.iTracParser.ParseBCD(arrData[0]));
                //double num = ParseCoordinate(arrData, 15);
                //double num1 = ParseCoordinate(arrData, 19);
                //double num2 = (double)(ParseBCD(arrData[23]) * 100 + ParseBCD(arrData[24]));
                //double num3 = (double)(ParseBCD(arrData[25]) * 100 + ParseBCD(arrData[26]));
                //bool flag = (arrData[27] & 128) != 0;
                //str.AppendLine("TrackPoint");
                //str.AppendLine("num: " + num.ToString());
                //str.AppendLine("num1: " + num1.ToString());
                //str.AppendLine("num2: " + num2.ToString());
                //str.AppendLine("num3: " + num3.ToString());


                for (int i=23; i < arrData.Length; i++)
                {
                    str.AppendLine(i.ToString() + "Value: 128: " + Convert.ToString((arrData[i] & 128) != 0));
                    str.AppendLine(i.ToString() + "Value:  64: " + Convert.ToString((arrData[i] & 64) != 0));
                    str.AppendLine(i.ToString() + "Value:  32: " + Convert.ToString((arrData[i] & 32) != 0));
                    str.AppendLine(i.ToString() + "Value:  16: " + Convert.ToString((arrData[i] & 16) != 0));
                    str.AppendLine(i.ToString() + "Value:   8: " + Convert.ToString((arrData[i] & 8) != 0));
                    str.AppendLine(i.ToString() + "Value:   4: " + Convert.ToString((arrData[i] & 4) != 0));
                    str.AppendLine(i.ToString() + "Value:   2: " + Convert.ToString((arrData[i] & 2) != 0));
                    str.AppendLine(i.ToString() + "Value:   1: " + Convert.ToString((arrData[i] & 1) != 0));
                    str.AppendLine(i.ToString() + "Value:   0: " + Convert.ToString((arrData[i] & 0) != 0));
                    str.AppendLine("-------------------");
                }
               


                //int num4 = arrData[29];
                //int num5 = arrData[30];
                //int num6 = arrData[31];
                //str.AppendLine(("ACC:" + Convert.ToString((num4 & 128) != 0)));
                //str.AppendLine(("Input1:" + Convert.ToString((num4 & 64) != 0)));
                //str.AppendLine(("Input2:" + Convert.ToString((num4 & 32) != 0)));
                //str.AppendLine(("MainPower:" + Convert.ToString((num4 & 8) != 0)));
                //str.AppendLine(("OilCutting:" + Convert.ToString((num4 & 4) != 0)));

                //str.AppendLine(("SOS:" + Convert.ToString((num5 & 128) != 0)));
                //str.AppendLine(("Overspeed:" + Convert.ToString((num5 & 64) != 0)));

                //str.AppendLine(("CircuitCutting:" + Convert.ToString((num6 & 32) != 0)));



                return str.ToString();

            }
            catch (Exception exception1)
            {
                Exception exception = exception1;
                // throw new FormatException(string.Format("Could not parse {0}", iTracParser.LogBinary(null, arrData)), exception);

                return "";
            }


        }

        public static DateTime ParseDateTime(byte[] arrData, int iStartIndex)
        {
            DateTime dateTime;
            bool flag = arrData[iStartIndex] != 0;
            if (flag)
            {
                int Year = ParseBCD(arrData[iStartIndex]) + 2000;


                dateTime = new DateTime(ParseBCD(arrData[iStartIndex]) + 2000, ParseBCD(arrData[iStartIndex + 1]), ParseBCD(arrData[iStartIndex + 2]), ParseBCD(arrData[iStartIndex + 3]), ParseBCD(arrData[iStartIndex + 4]), ParseBCD(arrData[iStartIndex + 5]), DateTimeKind.Utc);
            }
            else
            {
                dateTime = DateTime.MinValue;
            }
            return dateTime;
        }





        public static double ParseCoordinate(byte[] arrData, int iStartIndex)
        {
            string str;
            bool flag = (arrData[iStartIndex] & 128) != 0;
            
            StringBuilder stringBuilder = new StringBuilder();
            int num = arrData[iStartIndex] & 127;
            stringBuilder.AppendFormat("{0:X2}", num);
            stringBuilder.AppendFormat("{0:X2}", arrData[iStartIndex + 1]);
            num = ParseBCD(arrData[iStartIndex + 2]);
            stringBuilder.Append(num / 10);
            stringBuilder.Append(".");
            stringBuilder.Append(num % 10);
            stringBuilder.AppendFormat("{0:X2}", arrData[iStartIndex + 3]);
            string str1 = stringBuilder.ToString();
            if (flag)
            {
                str = "S";
            }
            else
            {
                str = "N";
            }
            double num1 = ParseNmeaCoordinate(str1, str);
            return num1;
        }

        public static int ParseBCD(byte bteData)
        {
            int num = (bteData & 15) + (bteData >> 4 & 15) * 10;
            return num;
        }

        public static double ParseNmeaCoordinate(string strField, string strHemi)
        {
            bool flag;
            bool flag1;
            double num = 0;
            if (!(strField != "") || !(strField != "0"))
            {
                flag = true;
            }
            else
            {
                flag = strField.IndexOf('.') != -1;
            }
            bool flag2 = flag;
            if (flag2)
            {
                try
                {
                    double num1 = ParseNmeaDouble(strField);
                    int num2 = (int)num1;
                    int num3 = num2 % 100;
                    int num4 = (num2 - num3) / 100;
                    num = (double)num4 + ((double)num3 + num1 - (double)num2) / 60;
                }
                catch (Exception exception1)
                {
                    Exception exception = exception1;
                  //  throw new NmeaFormatException(string.Concat(exception.Message, " '", strField, "'"));
                }
                flag2 = num <= 360;
                if (flag2)
                {
                    if (strHemi == "")
                    {
                        flag1 = false;
                    }
                    else
                    {
                        flag1 = strHemi != null;
                    }
                    flag2 = flag1;
                    if (flag2)
                    {
                        flag2 = !(strHemi == "E");
                        if (flag2)
                        {
                            flag2 = !(strHemi == "W");
                            if (flag2)
                            {
                                flag2 = !(strHemi == "N");
                                if (flag2)
                                {
                                    flag2 = !(strHemi == "S");
                                    if (flag2)
                                    {
                                        //throw new NmeaFormatException("Unknown hemisphere. Must be N, S, E or W.");
                                    }
                                    else
                                    {
                                        num = -num;
                                    }
                                }
                            }
                            else
                            {
                                num = -num;
                            }
                        }
                    }
                    double num5 = num;
                    return num5;
                }
                else
                {
                 ///   throw new NmeaFormatException(string.Concat("Value to big, cannot be NMEA coordinate. ", num));
                }
            }
            else
            {
                ///throw new NmeaFormatException(string.Concat("Value must contain \".\" '", strField, "'"));
            }

            return 0;
        }

        public static double ParseNmeaDouble(string strField)
        {
            bool flag;
            double num = 0;
            if (strField == null)
            {
                flag = false;
            }
            else
            {
                flag = !(strField == "");
            }
            bool flag1 = flag;
            if (flag1)
            {
                try
                {
                    num = double.Parse(strField, NumberStyles.Float, NumberFormatInfo.InvariantInfo);
                }
                catch (Exception exception1)
                {
                    Exception exception = exception1;
                    //throw new NmeaFormatException(string.Concat(exception.Message, " '", strField, "'"));
                }
            }
            else
            {
                num = 0;
            }
            double num1 = num;
            return num1;
        }
    }
}
